package com.wawei.seeds.champion;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.AbsListView;
import android.widget.HeaderViewListAdapter;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.ViewSwitcher;

import com.wawei.seeds.R;
import com.wawei.seeds.adapter.ChampionBiddingFragmentAdapter;
import com.wawei.seeds.services.BiddingServiceHandler;
import com.wawei.seeds.services.SwitchImagesServiceHandler;
import com.wawei.seeds.utils.ImageLoader;
import com.wawei.seeds.utils.PrefUtils;
import com.wawei.seeds.utils.PullupToMoreListView;
import com.wawei.seeds.utils.RetrofitNetworkService;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.InjectViews;
import retrofit.RestAdapter;
import uk.co.senab.actionbarpulltorefresh.library.ActionBarPullToRefresh;
import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshLayout;
import uk.co.senab.actionbarpulltorefresh.library.listeners.OnRefreshListener;

/**
 * Created by parker on 15/6/7.
 */
public class ChampionBiddingTabFragment extends Fragment
        implements OnRefreshListener, ViewSwitcher.ViewFactory, AbsListView.OnScrollListener{
    private static final String TAG = "ChampionBiddingTabFragment";

    @InjectView(R.id.biddingList)
    PullupToMoreListView biddingListView;

    @InjectView(R.id.biddingPullRefresh)
    PullToRefreshLayout biddingPullRefresh;
    //Image switcher
    private ImageSwitcher adSwitcher;
    //Trick for showing images by image switcher
    private List<ImageView> imageViews;

    //Async operation (image loading, get bidding data etc.)
    private NotifyHandler notifyHandler;
    public static final int LOAD_SWITCH_IMAGE = 0x01;
    public static final int LOAD_NEW_BIDDING_DATA = 0x02;
    public static final int LOAD_OLD_BIDDING_DATA = 0x03;
    public static final int SCHEDULER_TRIGGER = 0x04;
    public static final int INIT_BIDDING_DATA = 0x05;

    //The dataset adapter for bidding list view
    private ChampionBiddingFragmentAdapter adapter;
    //Recording the position of current showing items
    private int currentFirstShowingItem = -1;

     //Scheduler for switching views automatically (10 seconds)
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    //Intervals of switching views
    private static final int IMAGE_SWITCH_INTERVAL = 10;

    private ListHeaderView listHeaderView;

    static class ListHeaderView {
        View view;
        @InjectView(R.id.adswitcher) ImageSwitcher imageSwitcher;
        @InjectViews({R.id.image1, R.id.image2}) List<ImageView> imageViews;
        public ListHeaderView(View view) {
            this.view = view;
            ButterKnife.inject(this, view);
        }
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(null != notifyHandler){
            notifyHandler.setTarget(this);
        }
        else {
            notifyHandler = new NotifyHandler(this);
        }
        //Initialize the list header view only one time
        View headerView = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_champion_bidding_header, null, false);
        listHeaderView = new ListHeaderView(headerView);

        adSwitcher = listHeaderView.imageSwitcher;
        imageViews = listHeaderView.imageViews;

        initViewSwitcher();
        initBiddingListDataset();
    }

    @Override
    public void onDestroy() {
        notifyHandler = null;
        super.onDestroy();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.tab_champion_bidding, container, false);
        ButterKnife.inject(this, view);

        initBiddingList();

        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        currentFirstShowingItem = PrefUtils.getFirstShowingItem(getActivity(), TAG);
    }

    @Override
    public void onPause() {
        super.onPause();
        PrefUtils.markFirstShowingItem(getActivity(), TAG ,currentFirstShowingItem);
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        return;
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        currentFirstShowingItem = firstVisibleItem;
    }

    /**
     * Initialize the view switcher as follows:
     * 1) set the animation effect : fly into screen from left, fly out of screen to right
     * 2) set the switcher's image view factory for 2 image views
     * 3) retrieve the urls of the images background
     */
    private void initViewSwitcher(){
        adSwitcher.setInAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.slide_in_left));
        adSwitcher.setOutAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.slide_out_right));
        adSwitcher.setFactory(this);

        //Get the switch images remote urls async
        //the notifyHandler will loading the real images by the remote urls
        SwitchImagesServiceHandler retriever = new SwitchImagesServiceHandler(getActivity());
        RestAdapter adapter = RetrofitNetworkService.makeAsyncRestAdapter();
        retriever.retrieveImages(adapter, 2, notifyHandler, LOAD_SWITCH_IMAGE);
    }

    /**
     * Initialize the bidding list including
     * 1. Load the last bidding list in local storage
     * 2. Start the async loading from the remote server to get the latest bidding list
     */
    private void initBiddingListDataset(){
        //TODO: load the last bidding list in local storage
        BiddingServiceHandler serviceHandler =
                new BiddingServiceHandler(ChampionBiddingTabFragment.this.getActivity());
        RestAdapter adapter = RetrofitNetworkService.makeAsyncRestAdapter();
        serviceHandler.retriveBidding(adapter, 0, notifyHandler, INIT_BIDDING_DATA);
    }

    /**
     * Initialize the bidding list as follows:
     * 1) initialize the pull refreshed list
     * 2) initialize the list data adapter for retrieving the bidding data from remote server
     */
    private void initBiddingList(){
        ActionBarPullToRefresh.from(getActivity())
                .theseChildrenArePullable(R.id.biddingList, R.id.adswitcher)
                .listener(this)
                .setup(biddingPullRefresh);


        biddingListView.addHeaderView(listHeaderView.view);
        biddingListView.setOnLoadMoreListener(new PullupToMoreListView.OnLoadMoreListener() {
            @Override
            public void onLoadMore() {
                BiddingServiceHandler serviceHandler =
                        new BiddingServiceHandler(ChampionBiddingTabFragment.this.getActivity());
                RestAdapter adapter = RetrofitNetworkService.makeAsyncRestAdapter();
                serviceHandler.retriveBidding(adapter, 0, notifyHandler, LOAD_OLD_BIDDING_DATA);
            }
        });
        //For storing the showing list items
        biddingListView.setOnScrollListener(this);


        if(null != adapter){
            biddingListView.setAdapter(adapter);
        }
        if(currentFirstShowingItem > -1){
            biddingListView.setSelection(currentFirstShowingItem);
        }
    }

    /**
     * This method is derived from ViewSwitcher.ViewFactory.
     * It'll be called if factory needs a new image view. We make the image background transparent.
     */
    @Override
    public View makeView() {
        ImageView view = new ImageView(getActivity());
        view.setBackgroundColor(Color.TRANSPARENT);
        view.setScaleType(ImageView.ScaleType.CENTER_CROP);
        view.setLayoutParams(new ViewSwitcher.LayoutParams
                (ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

        return view;
    }

    @Override
    public void onRefreshStarted(View view) {
        BiddingServiceHandler serviceHandler =
                new BiddingServiceHandler(ChampionBiddingTabFragment.this.getActivity());
        RestAdapter adapter = RetrofitNetworkService.makeAsyncRestAdapter();
        serviceHandler.retriveBidding(adapter, 0, notifyHandler, LOAD_NEW_BIDDING_DATA);
    }

    private static class NotifyHandler extends Handler{
        private WeakReference<ChampionBiddingTabFragment> mFragment;
        NotifyHandler(ChampionBiddingTabFragment fragment){
            mFragment = new WeakReference<ChampionBiddingTabFragment>(fragment);
        }

        public void setTarget(ChampionBiddingTabFragment fragment){
            if(null != fragment){
                mFragment.clear();
                mFragment = new WeakReference<ChampionBiddingTabFragment>(fragment);
            }
        }

        private List<ChampionBiddingFragmentAdapter.ChampionBiddingItem> extractListFromMessage(Message data){
            Bundle bundle = data.getData();
            Object[] ds = (Object[])bundle.get(RetrofitNetworkService.RESULT_DATA);
            List<ChampionBiddingFragmentAdapter.ChampionBiddingItem> items = new ArrayList<>(ds.length);
            for(Object o : ds){
                items.add((ChampionBiddingFragmentAdapter.ChampionBiddingItem)o);
            }
            return items;
        }

        @Override
        public void handleMessage(Message msg) {
            ChampionBiddingTabFragment fragment = mFragment.get();
            if(null != fragment) {
                if (msg.what == LOAD_SWITCH_IMAGE) {
                    Bundle data = msg.getData();
                    Object[] urls = (Object[])data.get(RetrofitNetworkService.RESULT_DATA);
                    if(null != urls){
                        String[] strs = new String[urls.length];
                        for(int i=0;i<strs.length;i++){
                            strs[i] = (String)urls[i];
                        }
                        ImageLoader loader = new ImageLoader(fragment.getActivity());
                        loader.loadImage(strs[0],
                                fragment.imageViews.get(0), false, false, false);

                        loader.loadImage(strs[1],
                                fragment.imageViews.get(1), false, false, false);

                        fragment.adSwitcher.setImageDrawable(fragment.imageViews.get(0).getDrawable());
                        fragment.startImageSwitcher(strs, this);
                    }
                }
                else if(msg.what == INIT_BIDDING_DATA){
                    List<ChampionBiddingFragmentAdapter.ChampionBiddingItem> items = extractListFromMessage(msg);
                    fragment.adapter = new ChampionBiddingFragmentAdapter(fragment.getActivity());
                    fragment.adapter.setDataset(items);
                    if(null != fragment.biddingListView) {
                        fragment.biddingListView.setAdapter(fragment.adapter);
                    }
                }
                else if(msg.what == LOAD_OLD_BIDDING_DATA){
                    List<ChampionBiddingFragmentAdapter.ChampionBiddingItem> items = extractListFromMessage(msg);
                    HeaderViewListAdapter headerViewListAdapter =
                            (HeaderViewListAdapter)fragment.biddingListView.getAdapter();
                    ChampionBiddingFragmentAdapter biddingFragmentAdapter =
                            (ChampionBiddingFragmentAdapter)headerViewListAdapter.getWrappedAdapter();

                    biddingFragmentAdapter.appendDataset(items);
                    biddingFragmentAdapter.notifyDataSetChanged();

                    fragment.biddingListView.onLoadMoreComplete();
                }
                else if(msg.what == LOAD_NEW_BIDDING_DATA){
                    List<ChampionBiddingFragmentAdapter.ChampionBiddingItem> items = extractListFromMessage(msg);
                    HeaderViewListAdapter headerViewListAdapter =
                            (HeaderViewListAdapter)fragment.biddingListView.getAdapter();
                    ChampionBiddingFragmentAdapter biddingFragmentAdapter =
                            (ChampionBiddingFragmentAdapter)headerViewListAdapter.getWrappedAdapter();

                    biddingFragmentAdapter.insertDataset(items);
                    biddingFragmentAdapter.notifyDataSetChanged();

                    fragment.biddingPullRefresh.setRefreshComplete();
                }
                else if(msg.what == SCHEDULER_TRIGGER){
                    int index = msg.getData().getInt("c");
                    fragment.adSwitcher.setImageDrawable(fragment.imageViews.get(index).getDrawable());
                }
            }
            super.handleMessage(msg);
        }
    }

    //Index of image changed in scheduler
    private static int c = 0;
    //If the scheduler is started or not
    private static boolean scheduled = false;

    /**
     * Start scheduler of the view switcher. The scheduler runs every 5 seconds, so the image will be
     * changed every 10 seconds.
     * Only one scheduler should being run at the same time.
     *
     * @param urls      the urls of images
     * @param handler   handler for showing the image in ui thread
     */
    private void startImageSwitcher(final String[] urls, final Handler handler){
        if(scheduled)
            return;
        final Runnable worker = new Runnable() {
            @Override
            public void run() {
                Bundle data = new Bundle();
                data.putInt("c",c);
                c = (c==0)?1:0;

                Message message = handler.obtainMessage();
                message.what = SCHEDULER_TRIGGER;
                message.setData(data);

                handler.sendMessage(message);
            }
        };

        final ScheduledFuture future = scheduler.scheduleAtFixedRate(worker, 0, IMAGE_SWITCH_INTERVAL, TimeUnit.SECONDS);
        scheduled = true;
        scheduler.schedule(new Runnable() {
            @Override
            public void run() {
                future.cancel(true);
                scheduled = false;
            }
        }, 60 * 60 , TimeUnit.SECONDS);
    }
}
